#include <iostream>
#include <memory>
#include <string>
using std::cout;
using std::endl;
using std::string;

class Computer
{
public:
    using ptr = std::shared_ptr<Computer>;
    Computer() {}
    void ToString()
    {
        cout << "电脑的信息：" << endl;
        printf("{\t主板：%s\n", _board.c_str());
        printf("\t显示器：%s\n", _display.c_str());
        printf("\t操作系统：%s\n}", _os.c_str());
    }

    void SetBoard(const string &board)
    {
        _board = board;
    }
    void SetDisplay(const string &display)
    {
        _display = display;
    }
    virtual void SetOs() = 0;

protected:
    std::string _board;
    std::string _os;
    std::string _display;
};

class MacBook : public Computer
{
public:
    MacBook() {}
    void SetOs() override
    {
        _os = "MAC OS X12";
    }
};

class Builder
{
public:
    using ptr = std::shared_ptr<Builder>;
    virtual Computer::ptr Build() = 0;
    virtual void BuildBoard(const string &board) = 0;
    virtual void BuildDisplay(const string &display) = 0;
    virtual void BuildOs() = 0;
};

class MacBookBuilder : public Builder
{
public:
    MacBookBuilder(Computer *cmp) : _computer(cmp) {}
    MacBookBuilder() : _computer(new MacBook()) {};
    void BuildBoard(const string &board) override
    {
        _computer->SetBoard(board);
    }
    void BuildDisplay(const string &display) override
    {
        _computer->SetDisplay(display);
    }
    void BuildOs() override
    {
        _computer->SetOs();
    }
    Computer::ptr Build()
    {
        return _computer;
    }

private:
    Computer::ptr _computer;
};

class Director
{
public:
    Director(Builder *builder) : _builder(builder) {}
    void BuildComputer(const string &board, const string &display)
    {
        _builder->BuildBoard(board);
        _builder->BuildDisplay(display);
        _builder->BuildOs();
    }

private:
    Builder::ptr _builder;
};

int main()
{
    Builder *builder = new MacBookBuilder;
    std::unique_ptr<Director> director(new Director(builder));
    director->BuildComputer("华硕主板", "AOC显示器");
    Computer::ptr computer = builder->Build();
    computer->ToString();
    return 0;
}